package com.flower.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.flower.domain.dto.buyer.order.CreateOrderDto;
import com.flower.domain.dto.buyer.order.OrderItemDto;
import com.flower.domain.dto.buyer.order.OrderQueryDto;
import com.flower.domain.dto.buyer.order.PaymentQRCodeDto;
import com.flower.domain.entity.*;
import com.flower.domain.vo.buyer.*;
import com.flower.mapper.*;
import com.flower.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.security.NoSuchAlgorithmException;

/**
 * @author 86178
 * @description 针对表【order(订单主表)】的数据库操作Service实现
 * @createDate 2025-03-04 12:26:59
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order>
        implements OrderService {

    @Autowired
    private OrderItemMapper orderItemMapper;

    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private AddressMapper addressMapper;

    @Autowired
    private CartMapper cartMapper;

    @Autowired
    private BuyerMapper buyerMapper;

    @Override
    public Page<OrderVO> getOrderList(Long buyerId, OrderQueryDto orderQueryDto) {
        // 构建查询条件
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();

        // 筛选条件
        if (orderQueryDto.getKeyword() != null && !orderQueryDto.getKeyword().isEmpty()) {
            wrapper.like(Order::getOrderNumber, orderQueryDto.getKeyword());
        }

        wrapper.eq(orderQueryDto.getStatus() != null, Order::getStatus, orderQueryDto.getStatus())
                .orderByDesc(Order::getCreateTime);

        // 时间范围查询
        if (orderQueryDto.getBeginTime() != null && !orderQueryDto.getBeginTime().isEmpty()) {
            wrapper.ge(Order::getCreateTime, orderQueryDto.getBeginTime() + " 00:00:00");
        }
        
        if (orderQueryDto.getEndTime() != null && !orderQueryDto.getEndTime().isEmpty()) {
            wrapper.le(Order::getCreateTime, orderQueryDto.getEndTime() + " 23:59:59");
        }

        // 店铺查询逻辑调整 - 当查询店铺订单时不需要限制buyerId
        if (orderQueryDto.getShopId() != null) {
            // 店铺订单查询 - 仅按店铺ID过滤
            wrapper.eq(Order::getShopId, orderQueryDto.getShopId());
        } else {
            // 买家订单查询 - 添加买家ID过滤
            wrapper.eq(Order::getBuyerId, buyerId)
                    .eq(Order::getShopId, 0);
        }

        // 分页查询订单
        Page<Order> orderPage = this.page(new Page<>(orderQueryDto.getPageNumber(), orderQueryDto.getPageSize()), wrapper);

        // 转换为VO
        List<OrderVO> orderVOs = orderPage.getRecords().stream().map(order -> {
            OrderVO vo = new OrderVO();
            BeanUtils.copyProperties(order, vo);
            Buyer buyer = buyerMapper.selectById(order.getBuyerId());
            vo.setBuyerName(buyer.getUsername());

            // 查询订单项
            List<OrderItem> items = orderItemMapper.selectByOrderId(order.getOrderId());
            List<OrderItemVO> itemVOs = items.stream().map(item -> {
                OrderItemVO itemVO = new OrderItemVO();
                BeanUtils.copyProperties(item, itemVO);
                Product product = productMapper.selectById(item.getProductId());
                itemVO.setImage(product.getImage());
                return itemVO;
            }).collect(Collectors.toList());
            vo.setProducts(itemVOs);

            return vo;
        }).collect(Collectors.toList());

        // 构建返回结果
        Page<OrderVO> result = new Page<>();
        BeanUtils.copyProperties(orderPage, result, "records");
        result.setRecords(orderVOs);
        return result;
    }

    @Override
    public OrderDetailVO getOrderDetail(Integer orderId, Long buyerId) {
        // 直接获取订单，不验证归属
        Order order = this.getById(orderId);

        // 构建订单详情VO
        OrderDetailVO detailVO = new OrderDetailVO();
        BeanUtils.copyProperties(order, detailVO);

        // 查询订单项
        List<OrderItem> items = orderItemMapper.selectByOrderId(orderId);
        List<OrderItemVO> itemVOs = items.stream().map(item -> {
            OrderItemVO itemVO = new OrderItemVO();
            BeanUtils.copyProperties(item, itemVO);
            itemVO.setSubtotal(item.getPrice() * item.getQuantity());
            Product product = productMapper.selectById(item.getProductId());
            itemVO.setImage(product.getImage());
            return itemVO;
        }).collect(Collectors.toList());
        detailVO.setItems(itemVOs);

        // 查询地址信息
        Address address = addressMapper.selectById(order.getAddressId());
        if (address != null) {
            AddressVO addressVO = new AddressVO();
            BeanUtils.copyProperties(address, addressVO);
            detailVO.setAddress(addressVO);
        }

        return detailVO;
    }

    @Override
    @Transactional
    public Order createOrder(CreateOrderDto createOrderDto) {
        // 验证地址归属
        Address address = addressMapper.selectById(createOrderDto.getAddressId());
        if (address == null || !address.getBuyerId().equals(createOrderDto.getBuyerId())) {
            throw new RuntimeException("收货地址不存在或无权使用");
        }
        
        // 在后端重新计算订单金额，并验证与前端传入的金额是否匹配
        long calculatedAmount = 0;
        
        // 验证商品并重新计算金额
        for (OrderItemDto itemDto : createOrderDto.getItems()) {
            Product product = productMapper.selectById(itemDto.getProductId());
            if (product == null) {
                throw new RuntimeException("商品不存在");
            }

            if (product.getStatus() == 0) {
                throw new RuntimeException("商品已下架");
            }

            // 累加商品金额
            calculatedAmount += product.getPrice() * itemDto.getQuantity();
        }
        
        // 计算运费、税费等其他费用（示例）
        long shipping = calculateShippingFee(createOrderDto.getItems());
        long tax = calculateTaxFee(calculatedAmount);
        long discount = calculateDiscount(createOrderDto.getBuyerId(), createOrderDto.getItems());
        
        // 最终金额
        long finalAmount = calculatedAmount + shipping + tax - discount;
        
        // 验证前端传入的总金额是否与后端计算的金额一致（允许1分钱误差）
        if (Math.abs(finalAmount - createOrderDto.getTotalAmount()) > 1) {
            throw new RuntimeException("订单金额不匹配，请刷新页面重试");
        }
        
        // 检查并锁定库存
        checkAndLockStock(createOrderDto.getItems());
        
        // 创建订单签名（可选，增强安全性）
        String orderSign = generateOrderSign(createOrderDto.getBuyerId(), finalAmount);
        
        // 创建主订单
        Order mainOrder = new Order();
        mainOrder.setBuyerId(createOrderDto.getBuyerId());
        mainOrder.setAddressId(createOrderDto.getAddressId());
        mainOrder.setOrderNumber(generateOrderNo());
        mainOrder.setStatus(0); // 待支付
        mainOrder.setTotalAmount((int) finalAmount);
        mainOrder.setCreateTime(LocalDateTime.now());
        this.save(mainOrder);

        // 为对应的订单项创建子订单
        for (OrderItemDto itemDto : createOrderDto.getItems()) {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(mainOrder.getOrderId());
            orderItem.setProductId(itemDto.getProductId());
            Product product = productMapper.selectById(itemDto.getProductId());
            if (product != null) {
                orderItem.setProductName(product.getProductName());
                orderItem.setProductImage(product.getImage());
                orderItem.setPrice(product.getPrice());
                orderItem.setQuantity(itemDto.getQuantity());
                orderItem.setSubtotal(product.getPrice() * itemDto.getQuantity());
                orderItemMapper.insert(orderItem);
            }
        }

        // 按店铺分组商品
        Map<Integer, List<OrderItemDto>> shopItemsMap = createOrderDto.getItems().stream()
                .filter(item -> {
                    if (item.getShopId() == null) {
                        throw new RuntimeException("订单项中商品的店铺ID不能为空");
                    }
                    return true;
                })
                .collect(Collectors.groupingBy(OrderItemDto::getShopId));

        if (shopItemsMap.isEmpty()) {
            throw new RuntimeException("订单中没有有效的商品");
        }

        // 为每个店铺创建订单和订单项
        for (Map.Entry<Integer, List<OrderItemDto>> entry : shopItemsMap.entrySet()) {
            Integer shopId = entry.getKey();
            List<OrderItemDto> shopItems = entry.getValue();

            // 计算店铺订单总金额
            int shopTotalAmount = 0;
            for (OrderItemDto itemDto : shopItems) {
                Product product = productMapper.selectById(itemDto.getProductId());
                if (product == null) {
                    throw new RuntimeException("商品不存在");
                }
                shopTotalAmount += product.getPrice() * itemDto.getQuantity();
            }

            // 创建店铺订单
            Order shopOrder = new Order();
            shopOrder.setBuyerId(createOrderDto.getBuyerId());
            shopOrder.setAddressId(createOrderDto.getAddressId());
            shopOrder.setOrderNumber(mainOrder.getOrderNumber());
            shopOrder.setShopId(shopId);
            shopOrder.setStatus(0); // 待支付
            shopOrder.setTotalAmount(shopTotalAmount);
            shopOrder.setShopId(shopId);
            shopOrder.setCreateTime(LocalDateTime.now());
            this.save(shopOrder);

            // 创建店铺订单的订单项
            for (OrderItemDto itemDto : shopItems) {
                OrderItem orderItem = new OrderItem();
                orderItem.setOrderId(shopOrder.getOrderId());
                orderItem.setProductId(itemDto.getProductId());
                Product product = productMapper.selectById(itemDto.getProductId());
                if (product != null) {
                    orderItem.setProductName(product.getProductName());
                    orderItem.setProductImage(product.getImage());
                    orderItem.setPrice(product.getPrice());
                    orderItem.setQuantity(itemDto.getQuantity());
                    orderItem.setSubtotal(product.getPrice() * itemDto.getQuantity());
                    orderItemMapper.insert(orderItem);
                }
            }
        }

        return mainOrder;
    }

    @Override
    @Transactional
    public void cancelOrder(Integer orderId, Long buyerId) {
        // 直接获取订单，不验证归属
        Order order = this.getById(orderId);
        if (order.getStatus() != 0) {
            throw new RuntimeException("只能取消待支付的订单");
        }

        // 1. 获取主订单信息
        List<OrderItem> orderItems = orderItemMapper.selectByOrderId(order.getOrderId());
        
        // 恢复商品库存
        for (OrderItem item : orderItems) {
            try {
                // 恢复库存（增加库存，所以amount为正数）
                productMapper.updateStock(item.getProductId(), item.getQuantity());
                log.info("订单取消，恢复商品库存: 商品ID={}, 数量={}", item.getProductId(), item.getQuantity());
            } catch (Exception e) {
                log.error("恢复商品库存失败: 商品ID={}, 数量={}", item.getProductId(), item.getQuantity(), e);
                // 继续恢复其他商品库存，不中断流程
            }
        }

        // 2. 更新主订单状态为已完成（状态2）
        order.setStatus(4);
        order.setCancelTime(LocalDateTime.now());
        this.updateById(order);

        // 3. 使用Lambda表达式更新所有关联店铺订单状态
        this.update(new LambdaUpdateWrapper<Order>()
                .eq(Order::getOrderNumber, order.getOrderNumber()) // 根据订单号匹配
                .ne(Order::getOrderId, orderId) // 排除主订单自身（假设主订单没有shop_id）
                .set(Order::getStatus, 4)   // 设置为待收货状态
                .set(Order::getCancelTime, LocalDateTime.now()));
    }

    @Override
    @Transactional
    public void deleteOrder(Integer orderId, Long buyerId) {
        // 直接获取订单，不验证归属
        Order order = this.getById(orderId);
        if (order.getStatus() != 4 && order.getStatus() != 3) {
            throw new RuntimeException("只能删除已完成或已取消的订单");
        }

        // 删除订单
        orderItemMapper.deleteById(orderId);
    }

    @Override
    @Transactional
    public void confirmReceipt(Integer orderId, Long buyerId) {
        // 直接获取订单，不验证归属
        Order order = this.getById(orderId);
        if (order.getStatus() != 2) {
            throw new RuntimeException("订单状态错误");
        }

        // 1. 获取主订单信息
        List<OrderItem> orderItems = orderItemMapper.selectByOrderId(order.getOrderId());

        // 2. 更新主订单状态为已完成（状态2）
        order.setStatus(3);
        order.setFinishTime(LocalDateTime.now());
        this.updateById(order);

        // 3. 使用Lambda表达式更新所有关联店铺订单状态
        this.update(new LambdaUpdateWrapper<Order>()
                .eq(Order::getOrderNumber, order.getOrderNumber()) // 根据订单号匹配
                .ne(Order::getOrderId, orderId) // 排除主订单自身（假设主订单没有shop_id）
                .set(Order::getStatus, 3)   // 设置为待收货状态
                .set(Order::getFinishTime, LocalDateTime.now()));
    }

    @Override
    public PaymentQRCodeVO getPaymentQRCode(PaymentQRCodeDto paymentQRCodeDto, Long buyerId) {
        // 直接获取订单，不验证归属
        Order order = this.getById(paymentQRCodeDto.getOrderId());
        if (order.getStatus() != 0) {
            throw new RuntimeException("订单状态错误");
        }

        // 返回静态支付二维码
        PaymentQRCodeVO qrCodeVO = new PaymentQRCodeVO();
        
        // 根据支付方式返回对应的静态图片
        String qrCodePath;
        switch (paymentQRCodeDto.getPaymentMethod()) {
            case "alipay":
                qrCodePath = "/static/images/alipay_qrcode.png";
                break;
            case "wechat":
                qrCodePath = "/static/images/wechat_qrcode.png";
                break;
            case "unionpay":
                qrCodePath = "/static/images/unionpay_qrcode.png";
                break;
            default:
                qrCodePath = "/static/images/default_qrcode.png";
        }
        
        qrCodeVO.setQrCode(qrCodePath);
        qrCodeVO.setExpireTime(15 * 60); // 15分钟过期
        
        return qrCodeVO;
    }

    @Override
    public PaymentStatusVO checkPaymentStatus(Integer orderId, Long buyerId) {
        // 直接获取订单，不验证归属
        Order order = this.getById(orderId);

        PaymentStatusVO statusVO = new PaymentStatusVO();

        // 判断订单状态
        if (order.getStatus() > 0) {
            statusVO.setStatus("paid");
            statusVO.setRemainingTime(0);
        } else {
            // 计算剩余支付时间（假设15分钟内有效）
            LocalDateTime createTime = order.getCreateTime();
            LocalDateTime expireTime = createTime.plusMinutes(15);
            LocalDateTime now = LocalDateTime.now();

            if (now.isAfter(expireTime)) {
                statusVO.setStatus("expired");
                statusVO.setRemainingTime(0);
            } else {
                statusVO.setStatus("unpaid");
                statusVO.setRemainingTime((int) java.time.Duration.between(now, expireTime).getSeconds());
            }
        }

        return statusVO;
    }

    @Override
    public OrderStatusCountVO getOrderStatusCount(Long buyerId) {
        // 初始化返回对象
        OrderStatusCountVO countVO = new OrderStatusCountVO();

        // 替换LambdaQueryWrapper为QueryWrapper
        List<Map<String, Object>> statusCounts = this.baseMapper.selectMaps(
                new QueryWrapper<Order>()
                        .select("status", "COUNT(*) as count")
                        .eq("buyer_id", buyerId)
                        .eq("shop_id", 0)
                        .groupBy("status")
        );

        // 初始化计数
        countVO.setUnpaid(0);
        countVO.setUnshipped(0);
        countVO.setShipped(0);
        countVO.setCompleted(0);
        countVO.setChannel(0);

        // 处理查询结果
        int total = 0;
        for (Map<String, Object> statusCount : statusCounts) {
            Integer status = ((Number) statusCount.get("status")).intValue();
            Integer count = ((Number) statusCount.get("count")).intValue();
            total += count;

            switch (status) {
                case 0 -> countVO.setUnpaid(count);     // 待付款
                case 1 -> countVO.setUnshipped(count);   // 待发货
                case 2 -> countVO.setShipped(count);     // 待收货
                case 3 -> countVO.setCompleted(count);   // 已完成
                case 4 -> countVO.setChannel(count);     // 取消
            }
        }

        countVO.setTotal(total);
        return countVO;
    }

    @Override
    @Transactional
    public void payOrder(Integer orderId) {
        // 1. 获取主订单信息
        Order mainOrder = this.getById(orderId);
        List<OrderItem> orderItems = orderItemMapper.selectByOrderId(mainOrder.getOrderId());

        // 2. 更新主订单状态为待收货（状态2）
        mainOrder.setStatus(2);
        mainOrder.setPayTime(LocalDateTime.now());
        this.updateById(mainOrder);

        // 3. 使用Lambda表达式更新所有关联店铺订单状态
        this.update(new LambdaUpdateWrapper<Order>()
                .eq(Order::getOrderNumber, mainOrder.getOrderNumber()) // 根据订单号匹配
                .ne(Order::getOrderId, orderId) // 排除主订单自身（假设主订单没有shop_id）
                .set(Order::getStatus, 2)   // 设置为待收货状态
                .set(Order::getPayTime, LocalDateTime.now()));
        // 4.删除购物车中对应的商品
        orderItems.forEach(item -> {
            cartMapper.delete(new LambdaUpdateWrapper<Cart>()
                    .eq(Cart::getProductId, item.getProductId())
                    .eq(Cart::getBuyerId, mainOrder.getBuyerId()));
        });
    }

    @Override
    @Transactional
    public void updateOrderStatus(Integer orderId, Integer status) {
        // 获取订单
        Order order = this.getById(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        
        // 验证状态值合法性
        if (status < 0 || status > 5) {
            throw new RuntimeException("订单状态值无效");
        }
        
        // 检查状态流转是否合理
        if (!isValidStatusTransition(order.getStatus(), status)) {
            throw new RuntimeException("订单状态流转不合法");
        }
        
        // 更新主订单状态
        order.setStatus(status);
        
        // 设置相应的时间字段
        switch (status) {
            case 1: // 待发货
                order.setPayTime(LocalDateTime.now());
                break;
            case 2: // 待收货
                order.setShipTime(LocalDateTime.now());
                break;
            case 3: // 已完成
                order.setFinishTime(LocalDateTime.now());
                break;
            case 4: // 已取消
                order.setCancelTime(LocalDateTime.now());
                break;
            case 5: // 已退款
                // 对于退款状态，目前没有专门的时间字段，可以使用更新时间代替
                // order.setRefundTime(LocalDateTime.now());
                break;
            default:
                break;
        }
        
        // 更新订单
        this.updateById(order);
        
        // 如果是店铺订单，同时更新关联订单
        if (order.getShopId() != null && order.getShopId() > 0) {
            // 更新所有具有相同订单号的其他订单
            this.update(new LambdaUpdateWrapper<Order>()
                    .eq(Order::getOrderNumber, order.getOrderNumber())
                    .ne(Order::getOrderId, orderId)
                    .set(Order::getStatus, status)
                    .set(status == 1, Order::getPayTime, LocalDateTime.now())
                    .set(status == 2, Order::getShipTime, LocalDateTime.now())
                    .set(status == 3, Order::getFinishTime, LocalDateTime.now())
                    .set(status == 4, Order::getCancelTime, LocalDateTime.now())
                    // 对于退款状态，目前不设置特定时间字段
                    // .set(status == 5, Order::getRefundTime, LocalDateTime.now())
            );
        }
    }
    
    /**
     * 判断订单状态流转是否合法
     * @param currentStatus 当前状态
     * @param targetStatus 目标状态
     * @return 是否合法
     */
    private boolean isValidStatusTransition(Integer currentStatus, Integer targetStatus) {
        // 状态保持不变，直接返回true
        if (currentStatus.equals(targetStatus)) {
            return true;
        }
        
        // 按照业务逻辑定义合法的状态流转
        switch (currentStatus) {
            case 0: // 待付款 -> 已付款(待发货)或已取消
                return targetStatus == 1 || targetStatus == 4;
            case 1: // 待发货 -> 待收货或已取消或已退款
                return targetStatus == 2 || targetStatus == 4 || targetStatus == 5;
            case 2: // 待收货 -> 已完成或已退款
                return targetStatus == 3 || targetStatus == 5;
            case 3: // 已完成 -> 已退款
                return targetStatus == 5;
            case 4: // 已取消，终态，不能再变
                return false;
            case 5: // 已退款，终态，不能再变
                return false;
            default:
                return false;
        }
    }

    // 生成订单号
    private String generateOrderNo() {
        return LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
                + UUID.randomUUID().toString().substring(0, 6);
    }

    // 计算运费（示例实现）
    private long calculateShippingFee(List<OrderItemDto> items) {
        // 实际项目中可能根据商品重量、地区等因素计算运费
        return 0; // 示例为免运费
    }

    // 计算税费（示例实现）
    private long calculateTaxFee(long productAmount) {
        // 实际项目中可能根据不同地区税率计算
        return 0; // 示例为免税
    }

    // 计算优惠金额（示例实现）
    private long calculateDiscount(Integer buyerId, List<OrderItemDto> items) {
        // 实际项目中可能根据优惠券、活动规则等计算折扣
        return 0; // 示例为无折扣
    }

    // 生成订单签名（增强安全性）
    private String generateOrderSign(Integer buyerId, long amount) {
        try {
            // 使用买家ID、订单金额和密钥生成签名
            String dataToSign = buyerId + ":" + amount + ":" + System.currentTimeMillis() + ":YOUR_SECRET_KEY";
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            byte[] digest = md.digest(dataToSign.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(digest);
        } catch (NoSuchAlgorithmException e) {
            log.error("生成订单签名失败", e);
            return "";
        }
    }

    // 添加库存检查和锁定逻辑
    private void checkAndLockStock(List<OrderItemDto> items) {
        for (OrderItemDto item : items) {
            Product product = productMapper.selectById(item.getProductId());
            
            // 检查商品库存是否充足
            if (product.getStock() < item.getQuantity()) {
                throw new RuntimeException("商品 " + product.getProductName() + " 库存不足");
            }
            
            // 锁定库存
            int updated = productMapper.updateStock(product.getProductId(), -item.getQuantity());
            if (updated <= 0) {
                throw new RuntimeException("商品库存锁定失败，请重试");
            }
        }
    }

    // 在支付超时后恢复库存的方法
    @Scheduled(fixedDelay = 60000) // 每分钟执行一次
    public void handleExpiredOrders() {
        // 查找超过15分钟未支付的订单
        LocalDateTime expireTime = LocalDateTime.now().minusMinutes(15);
        
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getStatus, 0) // 待支付状态
               .lt(Order::getCreateTime, expireTime);
        
        List<Order> expiredOrders = this.list(wrapper);
        
        for (Order order : expiredOrders) {
            try {
                // 自动取消订单，不需要验证归属
                cancelOrder(order.getOrderId(), order.getBuyerId().longValue());
                log.info("自动取消超时未支付订单: {}", order.getOrderId());
            } catch (Exception e) {
                log.error("自动取消订单失败: {}", order.getOrderId(), e);
            }
        }
    }
}




